package be.rivendale.mathematics;

import org.apache.commons.lang.Validate;

/**
 * Represents a <a href="http://en.wikipedia.org/wiki/Line_segment">line segment</a>.
 * A line segment is a part of line, that is bounded by two points. All points on that line between the two bounding
 * points are part of the line segment.
 * <p>A line segment is thus a limited set of a line, and therefor implements mostly the same operations, but with
 * more restrictions.</p>
 */
public class LineSegment {
    /**
     * The line on which this line segment lies. The line has a lot of the same operations as the line segment, but
     * with more restrictions.
     */
    private Line line;

    /**
     * Creates a new line segment by two points that define it's bounding points.
     * <p>The two points must not be equal or null.</p>
     * @param a The first bounding point that limits this line segment.
     * @param b The second bounding point that limits this line segment.
     */
    public LineSegment(Point a, Point b) {
        this.line = new Line(a, b);
    }

    /**
     * Returns the second bounding point that limits this line segment.
     * @return A bounding point of this line segment.
     */
    public Point getB() {
        return line.getB();
    }

    /**
     * Returns the first bounding point that limits this line segment.
     * @return A bounding point of this line segment.
     */
    public Point getA() {
        return line.getA();
    }

    /**
     * Returns the direction of this linesegment.
     * <p>The direction vector is a vector that lies parallel to the line segment. Or otherwise put; the direction
     * vector is the vector that is "followed" by the line segment.</p>
     * <p>In this definition, there are acutally two possible direction vectors; the second point to the opposite
     * direction. This second direction vector, if desired, can be obtained by calling {@link Vector#invert()}</p>
     * on result of this method.
     * @see be.rivendale.mathematics.Line#direction()
     * @return One of the two direction vectors of this line segment.
     */
    public Vector direction() {
        return line.direction();
    }

    /**
     * Calculates a new point on this line segment.
     * <p>This is done by using the parametric equation <code>p = a + t*v</code></p> of the {@link Line} on which this
     * line segment lies, defined by the points 'a' and 'b'. In this equation, 'v' is the {@link #direction()
     * direction vector}, and 't' is the paremetic value of the equation. This parametric value is allowed any value
     * between zero and one, and is thus a restriction on the general form of the line equation.
     * @param t The parametric value of the line equation. Since this is a line segment, it's value is only allowed
     * between zero and one.
     * @return A point somewhere on this line segment.
     * @see Line#pointOnLine(double)
     */
    public Point pointOnLineSegment(double t) {
        Validate.isTrue(MathematicalUtilities.between(0, 1, t), "A point on a line segment can only be found when passing a value for 't' between zero and one");
        return line.pointOnLine(t);
    }
}
